﻿using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace Common
{
    public class CityService
    {
        /*
         * StackExchange.Redis
         */
        static IDatabase redis;
        static object lobject = new object();
        public CityService()
        {
            if (redis == null)
            {
                lock (lobject)
                {
                    if (redis == null)
                    {
                        ConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect(Common.AppSettings.AppSetting("Redis"));
                        redis = connectionMultiplexer.GetDatabase();
                    }
                }
            }

        }
        public IDatabase Redis { get { return redis; } }
    }

    public  class OperationRedis
    {
       // private static IDatabase db = new CityService().Redis;

        private static IDatabase db
        {
            get {
                return new CityService().Redis;
            }
        }


        #region List列表数据类型操作

        /// <summary>
        /// 移除并返回存储在该键列表的第一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public static string ListLeftPop(string redisKey)
        {
        
            return  db.ListLeftPop(redisKey);
        }

        /// <summary>
        /// 移除并返回存储在该键列表的最后一个元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public static string ListRightPop(string redisKey)
        {
          
            return db.ListRightPop(redisKey);
        }

        /// <summary>
        /// 移除列表指定键上与该值相同的元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public static long ListRemove(string redisKey, string redisValue)
        {
         
            return  db.ListRemove(redisKey, redisValue);
        }

        /// <summary>
        /// 在列表尾部插入值。如果键不存在，先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public static long ListRightPush(string redisKey, string redisValue)
        {
            return  db.ListRightPush(redisKey, redisValue);
        }

        /// <summary>
        /// 在列表头部插入值。如果键不存在，先创建再插入值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="redisValue"></param>
        /// <returns></returns>
        public static long ListLeftPush(string redisKey, string redisValue)
        {
           
            return  db.ListLeftPush(redisKey, redisValue);
        }

        /// <summary>
        /// 返回列表上该键的长度，如果不存在，返回 0
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public static long ListLength(string redisKey)
        {

            return  db.ListLength(redisKey);
        }

        /// <summary>
        /// 返回在该列表上键所对应的元素
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public static IEnumerable<RedisValue> ListRange(string redisKey)
        {
          
            return  db.ListRange(redisKey);
        }
        
        #endregion 


        #region Redis redis的分布式锁
        /// <summary>
        /// redis 加锁
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="Token">唯一码</param>
        /// <param name="Second">默认60秒,自动释放锁</param>
        /// <returns></returns>
        public static bool LockTake(string key,string Token, int Second = 60)
        {
            try
            {
                TimeSpan time = DateTime.Now.AddSeconds(Second) - DateTime.Now;
                return db.LockTake(key, Token, time);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// redis 解锁
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="Token">唯一码</param>
        /// <returns></returns>
        public static bool LockRelease(string key, string Token)
        {
            try
            {
                return db.LockRelease(key, Token);
            }
            catch
            {
                return false;
            }
        }
        #endregion
        #region Redis string数据类型操作
        /// <summary>
        /// 查询
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetValue(string key)
        {
            try
            {
                return db.StringGet(key);
            }
            catch 
            {
                return null;
            }
            
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool DeleteKey(string key)
        {
            return db.KeyDelete(key);
        }


        /// <summary>
        /// 增加/修改
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val">值</param>
        /// <param name="exp">过期时间</param>
        /// <returns></returns>
        public static bool StringSet(string key, string val, TimeSpan? exp = default(TimeSpan?))
        {
            try
            {
                return db.StringSet(key, val, exp);
            }
            catch
            {
                return false;
            }
          
        }


        /// <summary>
        ///  自增 Incr
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val">值</param>
        /// <returns></returns>
        public static long StringIncrement(string key)
        {
            return db.StringIncrement(key);
        }

        
        #endregion


         

        #region Redis Hash散列数据类型操作
        /// <summary>
        /// Redis散列数据类型  批量新增
        /// </summary>
        public static void HashSet(string key, List<HashEntry> hashEntrys)
        {
            db.HashSet(key, hashEntrys.ToArray());
        }
        /// <summary>
        /// Redis散列数据类型  新增一个
        /// </summary>
        /// <param name="key"></param>
        /// <param name="field"></param>
        /// <param name="val"></param>
        public static bool HashSet(string key, string field, string val)
        {
            return db.HashSet(key, field, val);
        }
        /// <summary>
        ///  Redis散列数据类型 获取指定key的指定field
        /// </summary>
        /// <param name="key"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        public static string HashGet(string key, string field)
        {
            return db.HashGet(key, field);
        }
        /// <summary>
        ///  Redis散列数据类型 获取所有field所有值,以 HashEntry[]形式返回
        /// </summary>
        /// <param name="key"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static HashEntry[] HashGetAll(string key)
        {
            return db.HashGetAll(key);
        }
       

        /// <summary>
        /// Redis散列数据类型 获取所有Key名称
        /// </summary>
        /// <param name="key"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static string[] HashGetAllKeys(string key)
        {
            return db.HashKeys(key).ToStringArray();
        }
        /// <summary>
        ///  Redis散列数据类型  单个删除field
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static bool HashDelete(string key, string hashField)
        {
            return db.HashDelete(key, hashField);
        }
        /// <summary>
        ///  Redis散列数据类型  批量删除field
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashFields"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static long HashDelete(string key, string[] hashFields)
        {
            List<RedisValue> list = new List<RedisValue>();
            for (int i = 0; i < hashFields.Length; i++)
            {
                list.Add(hashFields[i]);
            }
            return db.HashDelete(key, list.ToArray());
        }
        /// <summary>
        ///  Redis散列数据类型 判断指定键中是否存在此field
        /// </summary>
        /// <param name="key"></param>
        /// <param name="field"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static bool HashExists(string key, string field)
        {
            return db.HashExists(key, field);
        }
        /// <summary>
        /// Redis散列数据类型  获取指定key中field数量
        /// </summary>
        /// <param name="key"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static long HashLength(string key)
        {
            return db.HashLength(key);
        }
        /// <summary>
        /// Redis散列数据类型  为key中指定field增加incrVal值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="field"></param>
        /// <param name="incrVal"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        public static double HashIncrement(string key, string field, double incrVal)
        {
            return db.HashIncrement(key, field, incrVal);
        }
        #endregion
    }
}